#include "MulTask.h"
#include "stdlib.h"
#include "stdbool.h"
Task* p_head_task = NULL; //任务头指针，初始化时指向idle_task
TaskErrCode MulTask_Init(Task* p_idle_task,TaskCallBackFunc idle_cb ,void * p_context)
{
    if(p_idle_task == NULL)return TASK_ERR_NULL_TASK;
    p_head_task = p_idle_task; 
    p_idle_task->limit = 0;
    p_idle_task->tick = 0;
    p_idle_task->flag = false; //所有任务的flag初始化为false，方便第一次间隔地计时
    p_idle_task->cb = idle_cb;
    p_idle_task->p_context = p_context;
    p_idle_task->p_next_task = NULL; 
    //idle_task为第一个任务，类似头指针，只有idle任务的limit能等于0，
    return TASK_ERR_OK;
}

TaskErrCode MulTask_TaskInit(Task* p_task, uint16_t sep_tick, TaskCallBackFunc cb, void * p_context)
{
    if(p_task == NULL) //允许CB为null，因为提供了两种调用方式
        return TASK_ERR_NULL_TASK;
    if(sep_tick == 0) //不允许间隔时间为0，因为0表示idle任务
        return TASK_ERR_LIMIT;
    if(p_head_task == NULL)  //头指针还为Null,说明多任务没有初始化
        return TASK_ERR_NO_INIT_MULTASK;
    //初始化对应的成员
    p_task->flag = false;
    p_task->limit = sep_tick;
    p_task->tick = 0;
    p_task->cb = cb;
    p_task->p_context = p_context; 
    //回调函数的参数，可以用于传递一些值，避免task间的通信过多使用全局变量
    p_task->p_next_task = p_head_task->p_next_task;
    p_head_task->p_next_task = p_task; //头插法
    return TASK_ERR_OK;
}

TaskErrCode MulTask_Tick(void)
{
    Task * p_temp = NULL;
    if(p_head_task == NULL)  //头指针还为Null,说明多任务没有初始化
        return TASK_ERR_NO_INIT_MULTASK;
    p_temp = p_head_task->p_next_task; //指向第一个需要计算间隔的task
    while(p_temp != NULL)
    {
        if(p_temp->flag == false) //task需要计算间隔
        {
            if(p_temp->tick < p_temp->limit)p_temp->tick++;
            else 
            {
                p_temp->flag = true; //标志任务到期了，可以执行了
                p_temp->tick = 0;    //tick归0，方便计算下一个间隔
            }
        }
        p_temp = p_temp->p_next_task; //计算下一个task
    }
    return TASK_ERR_OK;
}

TaskErrCode MulTask_Loop(void)
{
    Task * p_temp = NULL;
    TaskErrCode ret = TASK_ERR_OK;
    if(p_head_task == NULL)  //头指针还为Null,说明多任务没有初始化
        return TASK_ERR_NO_INIT_MULTASK;
    p_temp = p_head_task->p_next_task; //指向第一个需要检查是否执行的task
    while(p_temp != NULL)
    {
        if(p_temp->flag == true)
            if(p_temp->cb != NULL)
                p_temp->cb(p_temp->p_context);
            else
                ret |= TASK_ERR_NULL_CB; //标记有一个task的回调函数为空，用于返回值提示
        p_temp->flag = false;
        p_temp = p_temp->p_next_task; //移交下一个task
    }
    //当所有到期任务执行结束后，才会开始执行idle任务
    if(p_head_task->cb != NULL)p_head_task->cb(p_head_task->p_context);
    else ret |= TASK_ERR_NULL_CB; 
    return ret;
}

TaskErrCode MulTask_SetTaskStartTick(Task * p_task, uint16_t tick)
{
    if(p_task == NULL)return TASK_ERR_NULL_TASK;
    if(tick > p_task->limit) return TASK_ERR_TICK; //设置的tick超过limit
    p_task->tick = tick;
    return TASK_ERR_OK;
}
